using System;
using System.Reflection;
using Microsoft.Practices.CompositeWeb.Interfaces;
using Microsoft.Practices.ObjectBuilder;
using WCSFContrib.Extensions.CompositeWeb.Interfaces;

namespace WCSFContrib.Extensions.CompositeWeb.BuilderStrategies
{
    /// <summary>
    /// Declares a <see cref="BuilderStrategy"/> that manages the values to get from the QueryString.
    /// </summary>
    /// <remarks>This strategy deals with the <see cref="QueryStringKeyAttribute"/> attribute.</remarks>
    public class QueryStringBindingStrategy : BuilderStrategy
    {
        /// <summary>
        /// Inspect  the object for <see cref="BuilderStrategy"/> and set the object field values accordingly.
        /// </summary>
        public override object BuildUp(IBuilderContext context, Type typeToBuild, object existing, string idToBuild)
        {
            IHttpContextLocatorService service = context.Locator.Get<IHttpContextLocatorService>(new DependencyResolutionLocatorKey(typeof(IHttpContextLocatorService), null));
            if (service != null)
            {
                IHttpContext httpContext = service.GetCurrentContext();
                if (httpContext != null)
                {
                    foreach (FieldInfo info in typeToBuild.GetFields())
                    {
                        this.SetFieldValue(context, existing, info, httpContext);
                    }
                }
            }

            return base.BuildUp(context, typeToBuild, existing, idToBuild);
        }

        private void SetFieldValue(IBuilderContext context, object existing, FieldInfo fieldInfo, IHttpContext httpContext)
        {
            if (IsQueryStringField(fieldInfo))
            {
                IQueryStringValue value2 = (IQueryStringValue)Activator.CreateInstance(fieldInfo.FieldType);
                value2.KeyName = GetKeyName(fieldInfo);
                value2.HttpContext = httpContext;
                fieldInfo.SetValue(existing, value2);
            }
        }

        private static bool IsQueryStringField(FieldInfo fieldInfo)
        {
            return typeof(IQueryStringValue).IsAssignableFrom(fieldInfo.FieldType);
        }

        private static string GetKeyName(FieldInfo fieldInfo)
        {
            return (GetQueryStringNameFromAttribute(fieldInfo) ?? (fieldInfo.Name));
        }

        private static string GetQueryStringNameFromAttribute(FieldInfo fieldInfo)
        {
            object[] customAttributes = fieldInfo.GetCustomAttributes(typeof(QueryStringKeyAttribute), false);
            return (((customAttributes != null) && (customAttributes.Length > 0)) ? ((QueryStringKeyAttribute)customAttributes[0]).QueryStringKeyName : null);
        }
    }
}